import bcrypt from 'bcrypt'
import jwt from 'jsonwebtoken'
import User from '../models/user'
import Conflicted from '../errors/conflicted'
import NotFound from '../errors/NotFoundError'
import BadRequest from '../errors/badReques'
import { JWT_SECRET_DEV } from '../utils/constants'
import { CREATED_CODE } from '../errors/statusCode'

const { NODE_ENV, JWT_SECRET } = process.env


export const createUser = (req, res, next) => {
  bcrypt.hash(req.body.password, 10)
    .then((hash) => User.create({
      email: req.body.email,
      password: hash,
      name: req.body.name,
      accessLevel: req.body.accessLevel
    }))
    .then((user) => res.status(CREATED_CODE).send({
      email: user.email,
      name: user.name,
      _id: user._id,
      accessLevel: user.accessLevel
    }))
    .catch((evt) => {
      if (evt.code === 11000) {
        next(new Conflicted('Такой пользователь уже существует'))
      } else if (evt.name === 'ValidationError') {
        next(new BadRequest('Переданы некорректные данные при создании пользователя'))
      } else {
        next(evt)
      }
    })
}

export const getCurrentUser = (req, res, next) => {
  const userId = req.user._id
  User.findById(userId)
    .orFail(() => {
      throw new NotFound('Пользователь по указанному _id не найден')
    })
    .then((user) => {
      res.send(user)
    })
    .catch((evt) => {
      if (evt.name === 'CastError') {
        next(new BadRequest('Запрашиваемый пользователь не найден'))
      } else {
        next(evt)
      }
    })
}

export const updateUser = (req, res, next) => {
  const { email, name, accessLevel } = req.body
  User.findByIdAndUpdate(
    req.user._id,
    { email, name, accessLevel },
    {
      new: true,
      runValidators: true,
    },
  )
    .orFail(() => {
      throw new NotFound('Пользователь с указанным _id не найден')
    })
    .then((user) => {
      res.send(user)
    })
    .catch((evt) => {
      if (evt.code === 11000) {
        next(new Conflicted('Такой пользователь уже существует'))
      } else if (evt.name === 'ValidationError') {
        next(new BadRequest('Переданы некорректные данные при обновлении профиля'))
      } else {
        next(evt)
      }
    })
}

export const login = (req, res, next) => {
  const { email, password } = req.body
  // @ts-ignore
  User.findUserByCredentials(email, password)
    .then((user) => {
      const token = jwt.sign(
        { _id: user._id },
        NODE_ENV === 'production' ? JWT_SECRET : JWT_SECRET_DEV,
        { expiresIn: '7d' },
      )
      res.status(200).send({ token })
    })
    .catch(next)
}
